/*
 * Created by Jaren at 2021/12/13 15:52
 */
import 'package:inmotion_protocol/common/product_model.dart';
import 'package:inmotion_protocol/common/product_version.dart';
import 'package:inmotion_protocol/common/vehicle_info.dart';
import 'package:inmotion_protocol/util/byte_util.dart';

abstract class InMotionProtocolException implements Exception {}

class ProtocolParseException implements InMotionProtocolException {
  final String _message;

  ProtocolParseException(this._message);

  @override
  String toString() => _message;
}

class NotSupportException implements InMotionProtocolException {
  final String _message;

  NotSupportException(this._message);

  @override
  String toString() => _message;
}

class SecurityConnectionFailedException implements InMotionProtocolException {
  SecurityConnectionFailedException([var message]);
}

class InvalidParamException implements InMotionProtocolException {
  InvalidParamException([var message]);
}

class NullCheckException implements InMotionProtocolException {
  NullCheckException([var message]);
}

class RequestProductPropertyFailedException implements InMotionProtocolException {
  static const int stepSN = 1;
  static const int stepModel = 2;
  static const int stepActivationTime = 3;
  static const int stepSoftwareVersion = 4;
  static const int stepHardwareVersion = 5;
  static const int stepDeviceInfo = 6;

  static const int errorTimeout = 0xFF;
  static const int errorParseFailed = 0xFE;

  int step;
  int error;

  RequestProductPropertyFailedException(this.step, this.error);

  static RequestProductPropertyFailedException byDeviceInfoTimeout() {
    return RequestProductPropertyFailedException(stepDeviceInfo, errorTimeout);
  }

  static RequestProductPropertyFailedException byDeviceInfoParseFailed() {
    return RequestProductPropertyFailedException(stepDeviceInfo, errorParseFailed);
  }

  static RequestProductPropertyFailedException bySNTimeout() {
    return RequestProductPropertyFailedException(stepSN, errorTimeout);
  }

  static RequestProductPropertyFailedException bySNParseFailed() {
    return RequestProductPropertyFailedException(stepSN, errorParseFailed);
  }

  static RequestProductPropertyFailedException byModelTimeout() {
    return RequestProductPropertyFailedException(stepModel, errorTimeout);
  }

  static RequestProductPropertyFailedException byModelParseFailed() {
    return RequestProductPropertyFailedException(stepModel, errorParseFailed);
  }

  static RequestProductPropertyFailedException byActivatedTimeTimeout() {
    return RequestProductPropertyFailedException(stepActivationTime, errorTimeout);
  }

  static RequestProductPropertyFailedException byActivatedTimeParseFailed() {
    return RequestProductPropertyFailedException(stepActivationTime, errorParseFailed);
  }

  static RequestProductPropertyFailedException bySoftwareVersionTimeout() {
    return RequestProductPropertyFailedException(stepSoftwareVersion, errorTimeout);
  }

  static RequestProductPropertyFailedException bySoftwareVersionParseFailed() {
    return RequestProductPropertyFailedException(stepSoftwareVersion, errorParseFailed);
  }

  static RequestProductPropertyFailedException byHardwareVersionTimeout() {
    return RequestProductPropertyFailedException(stepHardwareVersion, errorTimeout);
  }

  static RequestProductPropertyFailedException byHardwareVersionParseFailed() {
    return RequestProductPropertyFailedException(stepHardwareVersion, errorParseFailed);
  }

  String formatErrorCode() {
    return (ByteUtil.byte2Hex(step) + ByteUtil.byte2Hex(error)).toUpperCase();
  }

  @override
  String toString() {
    return 'RequestProductPropertyFailedException{step: $step, error: $error}';
  }
}

class DeviceRequestingUpdateException implements InMotionProtocolException {
  int device;
  ProductProperty? productProperty;

  DeviceRequestingUpdateException(this.device, String sn, ProductModel model, VersionWrapper versionWrapper) {
    productProperty = ProductProperty(sn, model, null, versionWrapper);
  }
}
